{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# Getting started with Cirq and IonQ on Azure Quantum\n",
    "\n",
    "This notebook shows how to send a basic quantum circuit expressed using the [Cirq library](https://quantumai.google/cirq) to an IonQ target via the Azure Quantum service."
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "First, install `azure-quantum` with the Cirq dependencies:"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "source": [
    "# To install the Azure Quantum client package with support for\n",
    "# Cirq, uncomment and run the line below:\n",
    "#\n",
    "# !pip install azure-quantum[cirq]==0.19.2109.165653 --quiet"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Connecting to the Azure Quantum service\n",
    "\n",
    "To connect to the Azure Quantum service, find the resource ID and location of your Workspace from the Azure portal here: https://portal.azure.com. Navigate to your Azure Quantum workspace and copy the values from the header.\n",
    "\n",
    "<img src=\"../azure-quantum-resource-id.png\" alt=\"How to retrieve the resource ID and location from an Azure Quantum workspace\">"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "Paste the values into the `AzureQuantumService` constructor below to create a `service` that connects to your Azure Quantum Workspace. Optionally, specify a default target:"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "source": [
    "from azure.quantum.cirq import AzureQuantumService\n",
    "service = AzureQuantumService(\n",
    "    resource_id=\"\",\n",
    "    location=\"\",\n",
    "    default_target=\"ionq.simulator\"\n",
    ")"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### List all targets\n",
    "\n",
    "You can now list all the targets that you have access to, including the current queue time and availability. Running this method will trigger authentication to your Microsoft account, if you're not already logged in."
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "source": [
    "service.targets()"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "[<Target name=\"ionq.qpu\", avg. queue time=19 s, Available>,\n",
       " <Target name=\"ionq.simulator\", avg. queue time=0 s, Available>,\n",
       " <Target name=\"quantinuum.qpu.h1-1\", avg. queue time=0 s, Unavailable>,\n",
       " <Target name=\"quantinuum.sim.h1-1sc\", avg. queue time=0 s, Available>,\n",
       " <Target name=\"quantinuum.sim.h1-1e\", avg. queue time=26 s, Available>]"
      ]
     },
     "metadata": {},
     "execution_count": 3
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Run a simple circuit\n",
    "\n",
    "Let's create a simple Cirq circuit to run. This circuit uses the square root of X gate, native to the IonQ hardware system.\n",
    "\n",
    "This notebook assumes some familiarity with Cirq. To read more about Cirq, review the [Cirq documentation](https://quantumai.google/cirq)."
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "source": [
    "import cirq\n",
    "\n",
    "q0, q1 = cirq.LineQubit.range(2)\n",
    "circuit = cirq.Circuit(\n",
    "    cirq.X(q0)**0.5,              # Square root of X\n",
    "    cirq.CX(q0, q1),              # CNOT\n",
    "    cirq.measure(q0, q1, key='b') # Measure both qubits\n",
    ")\n",
    "circuit"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "0: ───X^0.5───@───M('b')───\n",
       "              │   │\n",
       "1: ───────────X───M────────"
      ],
      "text/html": [
       "<pre style=\"overflow: auto; white-space: pre;\">0: ───X^0.5───@───M(&#x27;b&#x27;)───\n",
       "              │   │\n",
       "1: ───────────X───M────────</pre>"
      ]
     },
     "metadata": {},
     "execution_count": 4
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "You can now run the program via the Azure Quantum service and get the result. The following cell will submit a job that runs the circuit with 100 shots, wait until the job is completed and return the results."
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "source": [
    "result = service.run(program=circuit, repetitions=100)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "This returns a `cirq.Result` object."
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "source": [
    "print(result)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "b=0001101010110000111010001110010111010001101010001111100011100001111100101011101101001000001000011000, 0001101010110000111010001110010111010001101010001111100011100001111100101011101101001000001000011000\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Run on IonQ QPU\n",
    "\n",
    "#### Note: The time required to run a circuit on the QPU may vary depending on current queue times."
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "The previous job ran on the default simulator we specified, `\"ionq.simulator\"`. To run on the QPU, provide `\"ionq.qpu\"` as the `target` argument:"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "source": [
    "result = service.run(\n",
    "    program=circuit,\n",
    "    repetitions=100,\n",
    "    target=\"ionq.qpu\",\n",
    "    timeout_seconds=500 # Set timeout to 500 seconds to accomodate current queue time on QPU\n",
    ")"
   ],
   "outputs": [],
   "metadata": {
    "scrolled": true
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "Again, this returns a `cirq.Result` object."
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "source": [
    "print(result)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "b=0101011011011111100001011101101011011110100010000000011110111000100100110110101100110001001111101111, 0101011011011111100001011101101011011110100010000000011110111000100100110110101100110001001111101111\n",
      "\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Asynchronous model using Jobs\n",
    "\n",
    "For long-running circuits, it can be useful to run them asynchronously. The `service.create_job` method returns a `Job`, which you can use to get the results after the job has run successfully."
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "source": [
    "job = service.create_job(\n",
    "    program=circuit,\n",
    "    repetitions=100,\n",
    "    target=\"ionq.simulator\"\n",
    ")"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "To check on the job status, use `job.status()`:"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "source": [
    "job.status()"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "'ready'"
      ]
     },
     "metadata": {},
     "execution_count": 10
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "To wait for the job to be done and get the results, use the blocking call `job.results()`:"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "source": [
    "result = job.results()\n",
    "print(result)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "00: 0.5\n",
      "11: 0.5\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "Note that this does not return a `cirq.Result` object. Instead it returns a result object that is specific to the IonQ simulator and uses state probabilities instead of shot data."
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "source": [
    "type(result)"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "cirq_ionq.results.SimulatorResult"
      ]
     },
     "metadata": {},
     "execution_count": 12
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "To convert this to a `cirq.Result` object, use `result.to_cirq_result()`:"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "source": [
    "result.to_cirq_result()"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "b=1101000111010101101001011100001111101110011000100111101000010100101000001100010010011010111010011101, 1101000111010101101001011100001111101110011000100111101000010100101000001100010010011010111010011101"
      ]
     },
     "metadata": {},
     "execution_count": 13
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "source": [
    "# Print package versions used in this notebook\n",
    "import cirq\n",
    "print('\\n'.join(f'{m.__name__}=={m.__version__}' for m in globals().values() if getattr(m, '__version__', None)))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "cirq==0.12.0\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [],
   "outputs": [],
   "metadata": {}
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}